import SnakeNode from "./SnakeNode";
import Circle, { ICircle } from "../base/Circle";
import Config from "../config/Config";
import { V2Util } from "../util/V2Util";
import World from "../world/World";
import Snake from "./Snake";
import { Util } from "../util/Util";
import Chunk from "../world/Chunk";

const util = Util

/** 蛇头部参数接口 */
export interface ISnakeHead extends ICircle {
    /** 所在世界 */
    world: World,
    /** 节点所有者 */
    owner: Snake,
}

const v2 = V2Util
const cfg = Config.snake

/** 蛇头部节点类 */
export default class SnakeHead extends SnakeNode {

    /** 目标角度 */
    toAng: number;
    /** 冲刺状态 */
    isSprint: boolean = false;
    /** 当前冲刺倍率 */
    private _sprintScale: number = 1;
    /** 与保存点的距离 */
    private _saveDis: number = 0;
    /** 保存点路径 */
    private _savePath: Circle[]
    /** 移动速度 */
    private _moveSpd: number
    /** 转弯速度 */
    private _turnSpd: number

    constructor(obj: ISnakeHead) {
        super()
        this.set(obj)
        this._world = obj.world
        this._id = obj.world.getNewSnakeNodeId()
        this._owner = obj.owner
        this.toAng = this.ang;
        this._idx = 0;
        this.setWidth()
        this._savePath = [new Circle(this)]
        this.updateChunks()
    }

    /** 头部节点不回收到对象池 */
    recy() { }

    /** 从世界中销毁 */
    destory() {
        //从区块中删除
        this._chunks.forEach(chunk => chunk.removeSnakeHead(this))
        this._savePath = null
        super.destory()
    }

    /** 每帧执行 */
    update() {
        super.update()
        this.eatFood();
    }

    /** 每帧移动 */
    moving() {
        let dt = this._world.dt
        if (this.isSprint && this._owner.score > cfg.sprintCost) {
            //冲刺加速
            this._sprintScale += cfg.sprintSpd * (dt / cfg.sprintSpdTime);
            //消耗分数
            this._owner.score -= cfg.sprintCost * dt
        } else {
            //减速
            this._sprintScale -= 2 * cfg.sprintSpd * (dt / cfg.sprintSpdTime);
        }
        this._sprintScale = util.range(this._sprintScale, 1, cfg.sprintSpd);


        //计算移动距离和转弯角度
        let moveDis = this.getMoveDis()
        let turnAngle = this.getTurnAngle()

        //转弯移动
        this.offsetAng(turnAngle).moveForward(moveDis)

        //更新保存点距离
        this._saveDis += moveDis;
        if (this._saveDis > this._spacing) {
            let count = Math.floor(this._saveDis / this._spacing)
            this._saveDis %= this._spacing
            //记录保存点
            let path = this._savePath
            let len = path.length
            path.splice(len - count, len)
            while (count-- > 0) {
                path.unshift(this.cp().moveForward(-this._saveDis - this._spacing * count))
            }
        }
    }

    /** 进食 */
    eatFood() {
        //进食碰撞器
        let eatColl = this.cp().setW(this.w * cfg.eatRange)
        //碰撞器所在区块
        let chunks = this._world.getChunks(eatColl)
        //遍历区块中的食物节点
        this._world.getFoods(chunks).forEach(food => {
            if (eatColl.collide(food)) {
                this._owner.score += food.score
                food.eaten(this)
            }
        })
    }

    /** 碰撞检测 */
    collideCheck() {
        let collision: any = null;
        if (this._world.collideWall(this)) {
            collision = this._world;
        } else {
            //c1 c2 c3 ：头部碰撞器
            let r = this.r
            let dis = r / 2
            let rad = this.rad
            let c1 = this.cp().setW(r).moveForward(r / 2)
            let c2 = this.cp().setW(r).move(rad - Math.PI / 4, dis)
            let c3 = this.cp().setW(r).move(rad + Math.PI / 4, dis)
            //碰撞器所在区块
            let chunks = this._world.getChunks(this)
            //遍历区块中的蛇节点
            let nodes = this._world.getSnakeNodesExclude(chunks, [this.owner])
            nodes.some(node => {
                if (!collision) {
                    //其中一个碰撞器碰到则算碰撞
                    if (c1.collide(node) || c2.collide(node) || c3.collide(node)) {
                        collision = node.owner;
                        return true;
                    }
                }
            })
        }
        return collision;
    }

    onJoinChunk(chunk: Chunk) { chunk.addSnakeHead(this) }
    onExitChunk(chunk: Chunk) { chunk.removeSnakeHead(this) }

    // ================================================================

    /** 保存点路径 */
    get savePath() { return this._savePath }

    /** 与保存点的距离 */
    get saveDis() { return this._saveDis }

    /** 每秒移动距离 */
    getMoveSpd() {
        return cfg.initWidth * 8.88 + Math.pow(this.w - cfg.initWidth, 0.66) * 3.33;
    }

    /** 每秒转弯角度 */
    getTurnSpd() {
        let dis = (cfg.turnWidth * this.w * Math.PI) / 360
        return this._moveSpd / dis
    }
    /** 每帧移动距离 */
    getMoveDis() {
        return this._moveSpd * this._sprintScale * this._world.dt;
    }

    /** 每帧转弯角度 */
    getTurnAngle() {
        let angle = this._turnSpd * this._world.dt;
        let diff = v2.angDiff(this.ang, this.toAng);
        let sign = Math.sign(diff);
        return angle > Math.abs(diff) ? diff : sign * angle;
    }

    /** 设置宽度 */
    setWidth(w: number = this.w) {
        super.setWidth(w)
        this._moveSpd = this.getMoveSpd()
        this._turnSpd = this.getTurnSpd()
    }

}